﻿#pragma warning disable 1591

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

namespace TotalFreedomBST
{
    public class TabSection: BstSection
    {
        private HtmlHelper _htmlHelper;

        public Tab Tab { get; set; }

        public TabSection(HtmlHelper htmlHelper, Tab tab, string id, TabOptions options, RouteValueDictionary htmlAttributes)
            : base(htmlHelper.ViewContext, "</div></div>\r\n")
        {
            if (tab != null)
            {
                Tab = tab;
                if (htmlAttributes != null)
                    Tab.HtmlAttributes = htmlAttributes;
            }
            else
                Tab = new Tab(_htmlHelper, options, id, htmlAttributes);

            _htmlHelper = htmlHelper;
        }

        private string TabPaneList(TabPane parentTabPane = null)
        {
            IEnumerable<TabPane> tabPanes = Tab.TabPanes.Where(w => w.ParentTabPane == parentTabPane);
            string s = "";

            if (tabPanes.Any())
            {
                s = "<ul class=\"" + (parentTabPane == null ? "nav nav-tabs" : "dropdown-menu") + "\">\r\n";
                foreach (TabPane tabPane in tabPanes)
                {
                    bool isDropDown = (tabPane.Options & TabPaneOptions.Dropdown) == TabPaneOptions.Dropdown;

                    s += "<li";
                    if (((tabPane.Options & TabPaneOptions.Active) == TabPaneOptions.Active) || isDropDown)
                    {
                        s += " class=\"";
                        if ((tabPane.Options & TabPaneOptions.Active) == TabPaneOptions.Active)
                            s += "active";

                        if (isDropDown)
                            s += " dropdown";

                        s += "\"";
                    }

                    s += "><a href=\"#" + tabPane.Id + "\" data-toggle=\"" + (isDropDown ? "dropdown" : "tab") + "\">" + tabPane.Caption.ToHtmlString();

                    if ((tabPane.Options & TabPaneOptions.Caret) == TabPaneOptions.Caret)
                        s += "<b class=\"caret\"></b>";

                    s += "</a>";

                    s += TabPaneList(tabPane);

                    s += "</li>\r\n";
                }
                s += "</ul>\r\n";
            }

            return s;
        }

        public override string StartHtml()
        {
            string s = TabPaneList();
            return "<div " + BstHelperExtensions.AttributeOrDefault(Tab.HtmlAttributes, "id", Tab.Id) + BstHelperExtensions.AttributeOrDefault(Tab.HtmlAttributes, "class", null) + ">\r\n" + s + "<div class=\"tab-content\">";
        }

        public TabPaneSection TabPane(TabPane tabPane, object htmlAttributes = null)
        {
            TabPaneSection tabPaneSection = new TabPaneSection(this.Tab, _htmlHelper.ViewContext, tabPane);

            _htmlHelper.ViewContext.Writer.Write(tabPaneSection.StartHtml());

            return tabPaneSection;
        }

        public TabPane CreateTabPane(string id = null)
        {
            return Tab.CreateTabPane(id);
        }
    }

    [FlagsAttribute]
    public enum TabOptions
    {
        None = 0,
        Fade = 8
    }

    public interface ITab
    {
        HtmlHelper HtmlHelper { get; }
        bool IsFade();
    }

    public class Tab : ITab
    {
        public HtmlHelper HtmlHelper {get; private set;}
        public string Id { get; set; }
        public readonly List<TabPane> TabPanes = new List<TabPane>();
        public TabOptions Options { get;  set; }
        public RouteValueDictionary HtmlAttributes { get; set; }

        public Tab(HtmlHelper htmlHelper, TabOptions options, string id, RouteValueDictionary htmlAttributes)
        {
            HtmlHelper = htmlHelper;
            Options = options;
            HtmlAttributes = htmlAttributes;

            if (String.IsNullOrWhiteSpace(id))
                Id = System.Guid.NewGuid().ToString("N");
            else
                Id = id;
        }

        public bool IsFade()
        {
            return (Options & TabOptions.Fade) == TabOptions.Fade;
        }

        public TabPane CreateTabPane(string caption, TabPaneOptions options = TabPaneOptions.None, TabPane parentTabPane = null, string id = null, object htmlAttributes = null)
        {
            return CreateTabPane(new MvcHtmlString(HttpUtility.HtmlEncode(caption)), options, parentTabPane, id, htmlAttributes);
        }

        public TabPane CreateTabPane(IHtmlString caption, TabPaneOptions options = TabPaneOptions.None, TabPane parentTabPane = null, string id = null, object htmlAttributes = null)
        {
            RouteValueDictionary attrs = null;
            if (htmlAttributes != null)
                attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

            TabPane tabPane = new TabPane(this, caption, options, id, attrs);
            tabPane.ParentTabPane = parentTabPane;
            TabPanes.Add(tabPane);

            return tabPane;
        }
    }

    public class TabPaneSection : BstSection
    {
        private ITab _tab;
        public TabPane TabPane { get; set; }        

        public TabPaneSection(ITab tab, ViewContext viewContext, TabPane tabPane, string id = null)
            : base(viewContext, "</div>\r\n")
        {
            if (tab == null)
                throw (new ArgumentNullException());

            _tab = tab;
            TabPane = tabPane;
        }

        public override string StartHtml()
        {
            string attrClass = "tab-pane";
            string s = "<div ";

            bool isActive = (TabPane.Options & TabPaneOptions.Active) == TabPaneOptions.Active;
            if (isActive)
                attrClass += " active";

            if (_tab.IsFade())
                attrClass += " fade" + (isActive ? " in" : "");

            s += BstHelperExtensions.ValuePlusAttribute("class", attrClass, TabPane.HtmlAttributes);

            s += "\" " + BstHelperExtensions.AttributeOrDefault(TabPane.HtmlAttributes, "id", TabPane.Id) + ">\r\n";
            return s;
        }
    }

    [FlagsAttribute]
    public enum TabPaneOptions
    { 
        None = 0,
        Active = 1,
        Dropdown = 2,
        Caret = 4
    }

    public class TabPane
    {
        private readonly ITab _tab;
        public string Id { get; set; }
        public IHtmlString Caption { get; set; }
        public TabPaneOptions Options { get; set; }
        public TabPane ParentTabPane { get; set; }
        public RouteValueDictionary HtmlAttributes { get; set; }

        public TabPane(ITab tab, IHtmlString caption, TabPaneOptions options, string id, RouteValueDictionary htmlAttributes)
        {
            Caption = caption;
            Options = options;
            _tab = tab;

            if (String.IsNullOrWhiteSpace(id))
                Id = System.Guid.NewGuid().ToString("N");
            else
                Id = id;
        }

        public MvcHtmlString TabJS(string action = "toggle")
        {
            string s = "$('#" + Id + "').collapse('" + action + "');";
            return new MvcHtmlString(s);
        }

        public MvcHtmlString ToggleAttr()
        {
            string s = "data-toggle=\"collapse\" data-target=\"#" + Id + "\" ";

            return new MvcHtmlString(s);
        }

        public MvcHtmlString FromPartial(string partialName, object model = null, ViewDataDictionary viewData = null, object htmlAttributes = null)
        {
            string s = "<div class=\"tab-pane";

            if ((Options & TabPaneOptions.Active) == TabPaneOptions.Active)
                s += " active";

            if (_tab.IsFade())
                s += " fade";            

            s += "\" id=\"" + Id + "\">";
            s += _tab.HtmlHelper.Partial(partialName, model, viewData).ToHtmlString();
            s += "</div>";

            return new MvcHtmlString(s);
        }

        public MvcHtmlString ActivateTabJS(string action = "show")
        {
            string s = "$('a[href=\"#" + Id + "\"]').tab('" + action + "');";
            return new MvcHtmlString(s);
        }

        public MvcHtmlString ActivateTabAttr()
        {
            string s = "data-toggle=\"tab\" data-target=\"#" + Id + "\" ";

            return new MvcHtmlString(s);
        }
    }
}
